/* 
 * The <code>VBlock</code> contains a list of <code>VInst</code> in a basic block.  
 */

// VBlock.h
// This file defines class VBlock
#ifndef VBLOCK_H
#define VBLOCK_H

#include "crossbit/VInst.h"
#include "crossbit/VBlockBuilder.h"
#include <list>
#include <iterator>
#include <iostream>
#include <iomanip>

namespace crossbit {

    // For the beginning, VBlock is just an wrap class for list<VInst *>
    class VBlock {

        public:
            // the iterators of <code>vb_ilist</code>
            typedef std::list<VInst *>::iterator				vb_iterator;
            typedef std::list<VInst *>::const_iterator			vb_const_iterator;
            typedef std::list<VInst *>::reverse_iterator		vb_reverse_iterator;
            typedef std::list<VInst *>::const_reverse_iterator	vb_const_reverse_iterator;

            VBlock(XTMemAddr enter_spc) 
                : vb_enter_spc(enter_spc) { vb_next_spc = 0; end_of_call = false;}

            ~VBlock() { clear(); }
            void setEndOfCall( bool v ) {
                end_of_call = v;
            }
            bool isEndOfCall( void ) {
                return end_of_call;
            }

            void push_back(VInst * const inst) { vb_ilist.push_back(inst); }

            vb_iterator insert(vb_iterator it, VInst * const vinst) 
            { return vb_ilist.insert(it, vinst); }

            vb_iterator erase(vb_iterator it) 
            { return vb_ilist.erase(it); }

            XTUint32 size() const { return vb_ilist.size(); }

            bool empty() const { return vb_ilist.empty(); }

            void setVbIlist(XTInt32 index, VInst *inst)
            {
                if( index >= 0 && index <= vb_ilist.size() ){
                    vb_iterator it = vb_ilist.begin();
                    for( XTInt32 i = 0 ; i < index ; i++ , it++ );
                    (*it) = inst;
                } else
                    assert(0 && "Invalid Vinst index");
            }

            // instruction iterator methods
            vb_iterator		    		begin()			{ return vb_ilist.begin(); }
            vb_const_iterator			begin()	const	{ return vb_ilist.begin(); }
            vb_iterator		    		end()		    { return vb_ilist.end(); }
            vb_const_iterator			end()	const	{ return vb_ilist.end(); }
            vb_reverse_iterator			rbegin()		{ return vb_ilist.rbegin(); }
            vb_const_reverse_iterator	rbegin()const	{ return vb_ilist.rbegin(); }
            vb_reverse_iterator	    	rend()			{ return vb_ilist.rend(); }
            vb_const_reverse_iterator  	rend()	const	{ return vb_ilist.rend(); }

            void clear() 
            {
                for (vb_iterator it = vb_ilist.begin(); it != vb_ilist.end(); ++it)
                    delete (*it);
                vb_ilist.clear();
            }

            XTMemAddr enterSPC()	const	{ return vb_enter_spc; }
            XTMemAddr nextSPC()	const	{ return vb_next_spc; }

            void setVbNextSpc( XTMemAddr spc )
            {
                vb_next_spc = spc;
                return;
            }

            void print(std::ostream &os) {
                vb_iterator I = begin(),
                            E = end();

                for (int i = 0; I != E; ++I, ++i) {
                    os << std::setw(3) << std::right << i << ": " << **I << std::endl;
                }
            }

        private:
            // the entry address of the source binary code corresponding to the <code>VBlock</code> 
            XTMemAddr vb_enter_spc;
            // the following address of the source binary code to the basic block
            XTMemAddr vb_next_spc;
            // identify it this block is end of a call , that the last Vinst is JMP and the jump destination only
            // have one choice. 
            bool 	 end_of_call;
            // a list of <code>VInst</code> pointer of the basic block
            std::list<VInst *> vb_ilist;

            // forbid copy constructor
            VBlock(const VBlock &) {}

            // forbid copy assignment
            VBlock& operator=(const VBlock &) 
            { return *this; }     
    };

}

#endif
